#include "list.h"
#include "cpofsm.h"
#include "cpomqtt.h"
#include "es_print.h"
#include "cpodata.h"
#include "cpoprotocal.h"
#include "cpotimer.h"
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <signal.h>

extern struct mosquitto *mqtt_cpo;
extern bool clean_session;
extern bool unclean_session;

extern cpo_fsmsets_t cpo_sysfsmset[];

/* S_SYS_INIT -> S_SYSPOINTS_WAIT 时会打开一些系统点位
 * 打开的这些点位以及对应的开状态点位用这个链表头串起来, 
 * 以后其他线程可以轮询检查这些点位的状态，从而发送相关事件
 * 同时后续关掉设备也可以找到这些点位
 */
struct single_point syspoint_hd;

/* 子状态机的头 */
cpo_fsm_head_l *cpo_subfsm_hd;

cpo_dev_t *cpo_dev = NULL;

struct _subfsm_sn_t sf_sn;	// 记录当前子状态机正在操作的设备序号

pthread_t tid_state_ck = -1;
pthread_t tid_protocal = -1;
pthread_t tid_tm = -1;
pthread_t tid_upd_prop = -1;
pthread_t tid_ch_add_subtract = -1;
pthread_t tid_do_after_stop = -1;

/* 消息队列使用 */
key_t mkey;
int	mq_id = -1;	// 用于接收事件

/* 定时器线程使用 */
sigset_t tt_set;

struct _dk_repo dk_repo;

struct itimerval to_sigprop = {
    {0, 0},
    {1, 0}
};

int main(int argc, char *argv[])
{
	/* 冷源设备描述符创建 */
	cpo_dev = calloc(1, sizeof(cpo_dev_t));
	cpo_dev->add_dev = false;

	pthread_mutex_init(&cpo_dev->ct_head.lock, NULL);
	pthread_mutex_init(&cpo_dev->cwp_head.lock, NULL);
	pthread_mutex_init(&cpo_dev->pchwp_head.lock, NULL);
	pthread_mutex_init(&cpo_dev->ch_head.lock, NULL);

	pthread_mutex_init(&syspoint_hd.lock, NULL);

	INIT_LIST_HEAD(&cpo_dev->ct_head.list);
	INIT_LIST_HEAD(&cpo_dev->cwp_head.list);
	INIT_LIST_HEAD(&cpo_dev->pchwp_head.list);
	INIT_LIST_HEAD(&cpo_dev->ch_head.list);

	INIT_LIST_HEAD(&syspoint_hd.clist);
	INIT_LIST_HEAD(&syspoint_hd.slist);

	pthread_cond_init(&cpo_dev->deltmr_cond, NULL);

	/* init 子状态机头 */
	cpo_subfsm_hd = malloc(sizeof(cpo_fsm_head_l)*1);
	INIT_LIST_HEAD(&cpo_subfsm_hd->list);

	/* 消息队列初始化 */
	mkey = ftok("/bin/ls", 1);
	mq_id = msgget(mkey, 0600|IPC_CREAT);
	ES_PRT_INFO("Cpo create message queue, mq_id = %d \n", mq_id);
	if(mq_id < 0){
		ES_PRT_ERROR("%s \n", strerror(errno));
		exit(1);
	}

	/* 定时器线程使用, 阻塞接收alarm信号 */
	sigemptyset(&tt_set);
	sigaddset(&tt_set, SIGALRM);
    pthread_sigmask(SIG_BLOCK, &tt_set, NULL);

	signal(SIGPROF,sigroutine);

	/* mqtt init */
    mosquitto_lib_init();
	mqtt_cpo = mosquitto_new(NULL, clean_session, NULL);
	if(!mqtt_cpo){
        ES_PRT_ERROR("create mqtt client failed.. \n");
		goto mqttclean;
    }

    mosquitto_subscribe_callback_set(mqtt_cpo, cpo_mqtt_sub_cb);
	mosquitto_connect_callback_set(mqtt_cpo, cpo_mqtt_conn_cb);
	mosquitto_message_callback_set(mqtt_cpo, cpo_mqtt_msg_cb);

	if(MOSQ_ERR_SUCCESS != mosquitto_connect(mqtt_cpo, ES_MQTT_HOST, ES_MQTT_PORT, ES_MQTT_KEEPALIVE)){
		perror("Unable to connect.\n");
		goto mqttdestroy;
		return 1;
	}

	mosquitto_loop_start(mqtt_cpo);
    /* 订阅 "/local/gatewaydeviceKey/gatewaydeviceKey/command", 用于接收addDevice报文 */
	mosquitto_subscribe(mqtt_cpo, NULL, MQTT_SUB_INIT_CMD, 0);
	/* 订阅 "/local/gatewaydeviceKey/+", 用于接收更新实点value的报文 */
//	mosquitto_subscribe(mqtt_cpo, NULL, MQTT_SUB_REALPOINT, 0);

	/* msgrcv接收信息，然后分类处理 */
	pthread_create(&tid_protocal, NULL, cpo_event_thread, NULL);
	pthread_detach(tid_protocal);

	/* timer thread */
	pthread_create(&tid_tm, NULL, es_timer_thread, &tt_set);

	/* 更新运行状态有关的属性 */
	pthread_create(&tid_upd_prop, NULL, cpo_updprop_thread, NULL);
	pthread_detach(tid_upd_prop);

	/* 轮询检查和状态相关的点位, 根据不同情况发送不同事件 */
	pthread_create(&tid_state_ck, NULL, cpo_state_ck_thread, NULL);
	pthread_detach(tid_state_ck);

	/* 冷机加减机 */
	pthread_create(&tid_ch_add_subtract, NULL, cpo_ch_add_sub_thread, NULL);
	pthread_detach(tid_ch_add_subtract);

	pause();
    return 0;

mqttdestroy:
	mosquitto_destroy(mqtt_cpo);
mqttclean:
	mosquitto_lib_cleanup();

    return 1;
}